package pathx

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/pkg/errors"
)

// GetExePath 获取程序当前运行目录.
// 如果在IDE调试/运行,则返回工作目录
func GetExePath() (string, error) {
	exePath, err := os.Executable()
	if err != nil {
		return "", errors.Wrap(err, "获取程序执行路径")
	}

	exePath, err = filepath.EvalSymlinks(filepath.Dir(exePath))
	if err != nil {
		return "", errors.Wrap(err, "清除路径中的符号链接")
	}

	// 兼容go run / go test
	if strings.Contains(exePath, filepath.Dir(os.TempDir())) { // 个别电脑返回临时目录会携带/
		exePath, _ = os.Getwd()

		// 判断是否开启了Go module
		if os.Getenv("GO111MODULE") == "on" {
			// go.mod文件是否存在
		LOOP:
			if _, err := os.Stat(filepath.Join(exePath, "go.mod")); err != nil {
				if os.IsNotExist(err) {
					exePath = filepath.Dir(exePath)
					goto LOOP
				}
			}
		} else { // GOPATH模式
			srcPath := fmt.Sprintf("%s%s%s%s", os.Getenv("GOPATH"), string(filepath.Separator), "src", string(filepath.Separator)) // GOPATH/src/
			if strings.Contains(exePath, srcPath) {
				projectNameLength := strings.Index(exePath[len(srcPath):], string(filepath.Separator)) // 获取项目名的长度
				exePath = exePath[:len(srcPath)+projectNameLength]
			}
		}
	}

	return exePath, nil
}
